#include "mqtt.h"

#include "DHT11.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "cJSON.h"
#include "esp_log.h"
#include "esp_event.h"
#include "esp_event_loop.h"
#include "mqtt_client.h"
#include "ws2812.h"

//设备信息
#define DEVICE_TYPE "aithinker"

static const char *TAG = "MQTT Log";

static bool isConnect2Server = false;

typedef struct __User_data
{
	char allData[1024];
	int dataLen;
} User_data;

User_data user_data;

xTaskHandle handleMqtt = NULL;
xTaskHandle mHandlerParseJSON = NULL;	  //任务队列
xTaskHandle PortDataTaskHandle = NULL;	  //任务队列
xQueueHandle ParseJSONQueueHandler = NULL; //解析json数据的队列

//mqtt
esp_mqtt_client_handle_t client;
char MqttTopicSub[30], MqttTopicPub[30];
static char deviceUUID[17];

/*
 * @Description: 上报数据到服务器
 * @param: null
 * @return:
*/
void post_data_to_clouds(void *parm)
{
	BaseType_t err;
	float* temp;
	double temp_out[2] = {0.0};
	long Pressure = 0;
	double UVindex = 0;
	int SendEnable = 0;

	while(1)
	{
		if (!isConnect2Server)
		{
			vTaskDelay(500 / portTICK_PERIOD_MS);
		}
		else
		{

			extern xQueueHandle SHT31ToMqttQueueHandler;
			extern xQueueHandle BMP280ToMqttQueueHandler;
			extern xQueueHandle S12SDToMqttQueueHandler;
			if(SHT31ToMqttQueueHandler != NULL)
			{
				err=xQueueReceive(SHT31ToMqttQueueHandler, &temp, portMAX_DELAY);
				if(err==pdTRUE)
				{
					//为了保留小数点后两位，要不后面有一堆数
					temp_out[0] = (int)(temp[0]*100)/100.0;
					temp_out[1] = (int)(temp[1]*100)/100.0;
					SendEnable = SendEnable | 0x01;
				}
			}
			if(BMP280ToMqttQueueHandler != NULL)
			{
				err=xQueueReceive(BMP280ToMqttQueueHandler, &Pressure, portMAX_DELAY);
				if(err==pdTRUE)
				{
					SendEnable = SendEnable | 0x02;
				}
			}
			if(S12SDToMqttQueueHandler != NULL)
			{
				float UVindexf;
				err=xQueueReceive(S12SDToMqttQueueHandler, &UVindexf, portMAX_DELAY);
				//为了保留小数点后两位，要不后面有一堆数
				UVindex = (int)(UVindexf*100)/100.0;
				if(err==pdTRUE)
				{
					SendEnable = SendEnable | 0x04;
				}
			}
			if(SendEnable == 0x07)
			{
				cJSON *pData = cJSON_CreateObject();
				cJSON_AddNumberToObject(pData, "temperature", temp_out[0]);
				cJSON_AddNumberToObject(pData, "humidity", temp_out[1]);
				cJSON_AddNumberToObject(pData, "pressure", (double)Pressure/1000.0);
				cJSON_AddNumberToObject(pData, "uvindex", UVindex);

				char *s = cJSON_Print(pData);
				//ESP_LOGI(TAG, "post_data_to_clouds topic end : %s", MqttTopicPub);
				//ESP_LOGI(TAG, "post_data_to_clouds payload : %s", s);
				esp_mqtt_client_publish(client, MqttTopicPub, s, strlen(s), 1, 0);

				cJSON_free((void *)s);
				cJSON_Delete(pData);

				SendEnable = 0x00;
			}

			vTaskDelay(1000/portTICK_PERIOD_MS);
		}
	}
}

/*
 * @Description: 解析下发数据的队列逻辑处理
 * @param: null
 * @return:
*/
void Task_ParseJSON(void *pvParameters)
{
	printf("[SY] Task_ParseJSON_Message creat ... \n");
	while (1)
	{
		struct __User_data *pMqttMsg;

		printf("[%d] Task_ParseJSON_Message xQueueReceive wait ... \n", esp_get_free_heap_size());
		xQueueReceive(ParseJSONQueueHandler, &pMqttMsg, portMAX_DELAY);
	}
}
/*
 * @Description: MQTT服务器的下发消息回调
 * @param:
 * @return:
*/
esp_err_t MqttCloudsCallBack(esp_mqtt_event_handle_t event)
{
	int msg_id;
	client = event->client;
	switch (event->event_id)
	{
		//连接成功
	case MQTT_EVENT_CONNECTED:
		ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
		msg_id = esp_mqtt_client_subscribe(client, MqttTopicSub, 1);
		ESP_LOGI(TAG, "sent subscribe[%s] successful, msg_id=%d", MqttTopicSub, msg_id);
		ESP_LOGI(TAG, "[APP] Free memory: %d bytes", esp_get_free_heap_size());
		//post_data_to_clouds();
		isConnect2Server = true;

		if (ParseJSONQueueHandler == NULL)
			ParseJSONQueueHandler = xQueueCreate(5, sizeof(struct esp_mqtt_msg_type *));

		WS2812BSend_24bit(0x00, 0xFF, 0x00);
		if(PortDataTaskHandle == NULL)
		{
			xTaskCreate(post_data_to_clouds, "post_data_to_clouds", 1024*4, NULL, 10, &PortDataTaskHandle);
		}

		//开启json解析线程
		if (mHandlerParseJSON == NULL)
		{
			xTaskCreate(Task_ParseJSON, "Task_ParseJSON", 1024, NULL, 9, &mHandlerParseJSON);
		}

		break;
		//断开连接回调
	case MQTT_EVENT_DISCONNECTED:
		ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
		WS2812BSend_24bit(0x00, 0x00, 0xFF);
		isConnect2Server = false;
		esp_restart();
		break;
		//订阅成功
	case MQTT_EVENT_SUBSCRIBED:
		ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
		break;
		//订阅失败
	case MQTT_EVENT_UNSUBSCRIBED:
		ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
		break;
		//推送发布消息成功
	case MQTT_EVENT_PUBLISHED:
		ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
		break;
		//服务器下发消息到本地成功接收回调
	case MQTT_EVENT_DATA:
	{
		ESP_LOGI(TAG, " xQueueReceive  data [%s] \n", event->data);
		//发送数据到队列
		struct __User_data *pTmper;
		sprintf(user_data.allData, "%s", event->data);
		pTmper = &user_data;
		user_data.dataLen = event->data_len;
		xQueueSend(ParseJSONQueueHandler, (void *)&pTmper, portMAX_DELAY);
		break;
	}
	default:
		break;
	}
	return ESP_OK;
}

/*
 * @Description: MQTT参数连接的配置
 * @param:
 * @return:
*/
void TaskXMqttRecieve(void *p)
{
	//获取mac地址（station模式）
	uint8_t mac[6];
	esp_read_mac(mac, ESP_MAC_WIFI_STA);
	sprintf(deviceUUID, "%02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
	//组建MQTT订阅的主题
	//sprintf(MqttTopicSub, "/%s/%s/devSub", DEVICE_TYPE, deviceUUID);
	//组建MQTT推送的主题
	//sprintf(MqttTopicPub, "/%s/%s/devPub", DEVICE_TYPE, deviceUUID);

	sprintf(MqttTopicPub, "office/sensor1");
	printf("SENSOR_OPEN\n");

	//连接的配置参数
	esp_mqtt_client_config_t mqtt_cfg = {
		.host = "42.193.109.108", //连接的域名 ，请务必修改为您的
		.port = 1883,			   //端口，请务必修改为您的
		.username = "homeassistant",	   //用户名，请务必修改为您的
		.password = "rieth3aiYie2yohZaghai0Rohv0evaish7weed4Chigetho7phohgaingoh5Ahth",   //密码，请务必修改为您的
		.client_id = deviceUUID,
		.event_handle = MqttCloudsCallBack, //设置回调函数
		.keepalive = 120,					//心跳
		.disable_auto_reconnect = true,		//开启自动重连
		.disable_clean_session = false,		//开启 清除会话
	};
	client = esp_mqtt_client_init(&mqtt_cfg);
	esp_mqtt_client_start(client);

	vTaskDelete(NULL);
}
